#Loading Nessesary libraries for sentiment Analysis

library(sentimentr)
library(qdap)
library(jsonlite)
library(dplyr)
library(ggplot2)
library(tm)
library(tidyverse)
library(SentimentAnalysis)
library(quanteda)
library(xlsx)

#Creating API varible for “Article Search API FORMAT”

NYTIMES_KEY="a0HA3uBISDkGyvUGR3FeoAGybtDVPPM5"

#creating the query nessesary to extract wanted information

#Professor Johnson still has to give me the list of words nessesary for query

#Doesn’t seem like we can do “and” “or” for the specific query, something that academic search complete and pro quest are able to do

#Just do it for one month 2012/01/01 - 2012/02/01

#The default connector for values in parentheses is OR.

# Let's set some parameters
#term <- "immigrant+immigration" # Need to use + to string together separate words however it is concatinating
begin_date <- "19800101"
end_date <- "20191201"#change to 2 months to get data faster
#glocations <- "U.S"

#Searching for the terms that we query above and essentially creating the query object in order to use it for the API

#the https needs to be underlined

#immigrant OR migrant OR migration OR refugee OR asylum OR undocumented"

#it needs to be fq not q

baseurl <- paste0("http://api.nytimes.com/svc/search/v2/articlesearch.json?fq=immigrant OR immigration OR migrant OR migration OR refugee OR asylum OR undocumented", 
                  "&begin_date=",begin_date,"&end_date=",end_date,
                  "&facet_filter=true&api-key=",NYTIMES_KEY, sep=" ")

#Returning a Json object and calculating the max pages from the query, there is a max of 10 objects (newspaper articles) per page

initialQuery <- fromJSON(baseurl)
maxPages <- round((initialQuery$response$meta$hits[1] / 10)-1) 

#from the maxpages we are pasting the baseurl and retriving the information and putting it in a dataframe

#Putting the system to sleep in order to ‘trick’ the computer for the amount of requests made per minute

#query from JAN 2012 - 2019 JAN took >24 minutes to run with sleep 30

#it doesn’t like it when using %>% data.frame() in the end of the third line

#require(reshape2)
pages <- list()
for(i in 0:maxPages){
  nytSearch <- fromJSON(paste0(baseurl, "&page=", i), flatten = TRUE) %>% data.frame() 
  message("Retrieving page ", i)
  pages[[i+1]] <- nytSearch 
  Sys.sleep(30) #change to 5 to test on smaller datasets, 30 for actual execution
}
Retrieving page 0
Retrieving page 1
Retrieving page 2
Retrieving page 3
Retrieving page 4
Retrieving page 5
Retrieving page 6
Retrieving page 7
Retrieving page 8
Retrieving page 9
Retrieving page 10
Retrieving page 11
Retrieving page 12
Retrieving page 13
Retrieving page 14
Retrieving page 15
Retrieving page 16
Retrieving page 17
Retrieving page 18
Retrieving page 19
Retrieving page 20
Retrieving page 21
Retrieving page 22
Retrieving page 23
Retrieving page 24
Retrieving page 25
Retrieving page 26
Retrieving page 27
Retrieving page 28
Retrieving page 29
Retrieving page 30
Retrieving page 31
Retrieving page 32
Retrieving page 33
Retrieving page 34
Retrieving page 35
Retrieving page 36
Retrieving page 37
Retrieving page 38
Retrieving page 39
Retrieving page 40
Retrieving page 41
Retrieving page 42
Retrieving page 43
Retrieving page 44
Retrieving page 45
Retrieving page 46
Retrieving page 47
Retrieving page 48
Retrieving page 49
Retrieving page 50
Retrieving page 51
Retrieving page 52
Retrieving page 53
Retrieving page 54
Retrieving page 55
Retrieving page 56
Retrieving page 57
Retrieving page 58
Retrieving page 59
Retrieving page 60
Retrieving page 61
Retrieving page 62
Retrieving page 63
Retrieving page 64
Retrieving page 65
Retrieving page 66
Retrieving page 67
Retrieving page 68
Retrieving page 69
Retrieving page 70
Retrieving page 71
Retrieving page 72
Retrieving page 73
Retrieving page 74
Retrieving page 75
Retrieving page 76
Retrieving page 77
Retrieving page 78
Retrieving page 79
Retrieving page 80
Retrieving page 81
Retrieving page 82
Retrieving page 83
Retrieving page 84
Retrieving page 85
Retrieving page 86
Retrieving page 87
Retrieving page 88
Retrieving page 89
Retrieving page 90
Retrieving page 91
Retrieving page 92
Retrieving page 93
Retrieving page 94
Retrieving page 95
Retrieving page 96
Retrieving page 97
Retrieving page 98
Retrieving page 99
Retrieving page 100
Retrieving page 101
Retrieving page 102
Retrieving page 103
Retrieving page 104
Retrieving page 105
Retrieving page 106
Retrieving page 107
Retrieving page 108
Retrieving page 109
Retrieving page 110
Retrieving page 111
Retrieving page 112
Retrieving page 113
Retrieving page 114
Retrieving page 115
Retrieving page 116
Retrieving page 117
Retrieving page 118
Retrieving page 119
Retrieving page 120
Retrieving page 121
Retrieving page 122
Retrieving page 123
Retrieving page 124
Retrieving page 125
Retrieving page 126
Retrieving page 127
Retrieving page 128
Retrieving page 129
Retrieving page 130
Retrieving page 131
Retrieving page 132
Retrieving page 133
Retrieving page 134
Retrieving page 135
Retrieving page 136
Retrieving page 137
Retrieving page 138
Retrieving page 139
Retrieving page 140
Retrieving page 141
Retrieving page 142
Retrieving page 143
Retrieving page 144
Retrieving page 145
#as.data.frame(nyt)

#binding the pages for the new result

allNYTSearch <-rbind_pages(pages)

#binding the pages together and creating the final dataframe.

allNYTSearch20122019 <- rbind_pages(pages)

#creating a dataframe that are only “news”: Function part

#getting rid of anything that could not be “news” so that it doesn’t interact with wrong data

funct_remove_rows<- function(dataFrame,col_dataframe){
not_news_variable <- c("Interactive Feature", "Review", "Letter", "Correction","List")
allNYTSearch_OnlyNews<<-dataFrame[!grepl(paste(not_news_variable, collapse="|"), col_dataframe),]
return(allNYTSearch_OnlyNews)
}

#calling the function on the specific column of allNYTSearch and removing Co-ed and editorials

funct_remove_rows(allNYTSearch,allNYTSearch$response.docs.type_of_material)

#getting rid off foreign fiels in news

funct_remove_notUS<- function(dataFrame,col_dataframe){
not_world_variable <- c("Europe","Middle East")
allNYTSearch_OnlyNews_inUS<<-dataFrame[!grepl(paste(not_world_variable, collapse="|"), col_dataframe),]
return(allNYTSearch_OnlyNews_inUS)
}

#calling the functiion on

funct_remove_notUS(allNYTSearch_OnlyNews,allNYTSearch_OnlyNews$response.docs.subsection_name)

#Getting rid of white spaces #verify that this is right

allNYTSearch_OnlyNews_inUS$response.docs.lead_paragraph <-(str_squish(allNYTSearch_OnlyNews_inUS$response.docs.lead_paragraph))

#Add Id variable to the NYTSearch_OnlyNews

allNYTSearch_OnlyNews$id <- seq.int(nrow(allNYTSearch_OnlyNews))

#Convert datarame into term document matrix from the allNYTSearch_onlyNews

myCorpus <- Corpus(VectorSource(allNYTSearch_OnlyNews_inUS$response.docs.lead_paragraph))
dtm_NYTArticles <-  DocumentTermMatrix(myCorpus, 
                                   control = 
                                     list(removePunctuation = TRUE,
                                          stopwords = TRUE,
                                          tolower = TRUE,
              
                                          removeNumbers = TRUE)) 

#tidy format sentiment analysis

library(dplyr)
library(tidytext)
package 㤼㸱tidytext㤼㸲 was built under R version 3.6.1
ap_td <- tidy(dtm_NYTArticles)

#Sentiment from the tdm created above with tidyverse

ap_sentiments <- ap_td %>%
  inner_join(get_sentiments("bing"), by = c(term = "word"))

#Sentiment from SentimentAnalysis package with LM dicctionary

sentiment_scoreLM_cleancode<- analyzeSentiment(dtm_NYTArticles,
                              rules=list("SentimentLM"=list(ruleSentiment, loadDictionaryLM())))

#Sentiment from SentimentAnalysis package with GI dicctionary

sentiment_scoreGI_cleancode<- analyzeSentiment(dtm_NYTArticles,
                              rules=list("SentimentGI"=list(ruleSentiment, loadDictionaryGI())))

#Sentiment from SentimentAnalysis package from qdap dicctionary

sentiment_scoreQDAP_cleancode<- (analyzeSentiment(dtm_NYTArticles)$SentimentQDAP)
sentiment_scoreQDAP_DF<-as.data.frame(sentiment_scoreQDAP_cleancode)

#putting the dicctionaries in dataframe

LM_positive<-list((str(DictionaryLM[["negative"]])))
 chr [1:2355] "abandon" "abandoned" "abandoning" "abandonment" "abandonments" "abandons" "abdicated" "abdicates" ...
LM_negative <-list((str(DictionaryLM[["positive"]])))
 chr [1:354] "able" "abundance" "abundant" "acclaimed" "accomplish" "accomplished" "accomplishes" "accomplishing" ...
LM_uncertantity <-list((str(DictionaryLM[["uncertainty"]])))
 chr [1:297] "abeyance" "abeyances" "almost" "alteration" "alterations" "ambiguities" "ambiguity" "ambiguous" ...
LM_dicctionary <- do.call(rbind, Map(data.frame, A=LM_positive, B=LM_negative, LM_uncertantity))

#combininig 3 sentiment analysis datasets

all_sentiment_DF <- cbind(sentiment_scoreLM_cleancode,sentiment_scoreGI_cleancode,sentiment_scoreQDAP_DF)

#plotting sentiments

library(Hmisc)
hist.data.frame(all_sentiment_DF)

WORD CLOUD

library("SnowballC")
library("wordcloud")
package 㤼㸱wordcloud㤼㸲 was built under R version 3.6.1
library("RColorBrewer")

#Only run this for word cloud purposes

dtm_NYTArticles_word_cloud <-  TermDocumentMatrix(myCorpus, 
                                   control = 
                                     list(removePunctuation = TRUE,
                                          stopwords = TRUE,
                                          tolower = TRUE,
              
                                          removeNumbers = TRUE)) 
m <- as.matrix(dtm_NYTArticles_word_cloud)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
N <- 1
newd<-d[-(1:N), , drop = FALSE]
set.seed(1234)
wordcloud(words = newd$word, freq = d$freq, min.freq = 1,
          max.words=200, random.order=FALSE, rot.per=0.35, 
          colors=brewer.pal(8, "Dark2"))

#convert R markdown to R script

#knitr::purl("Clean_Code_Sentimentr.Rmd", "Script_Clean_Code_Sentiment", documentation = 2)

#code for the word values of a certain column

aggregate(data.frame(count = allNYTSearch_OnlyNews_inUS$response.docs.subsection_name), list(value = allNYTSearch_OnlyNews_inUS$response.docs.subsection_name), length)

#saving data from 2019 to 2012 for sentiment analysis

allNYTSearchtosave <- allNYTSearch
allNYTSearchtosave$response.docs.multimedia <- NULL
allNYTSearchtosave$response.docs.keywords <- NULL
allNYTSearchtosave$response.docs.byline.person<- NULL
#write.xlsx(allNYTSearch, 'allNYTSearch2012-2019-1459hits.xlsx')
write.table(allNYTSearchtosave, "allNYTSearch20122019hits.txt", sep="\t")
LS0tDQp0aXRsZTogIkNsZWFuIENvZGUgU2VudGltZW50UiB3aXRoIEFQSSBleHRyYWN0aW9uIG9mIGZpcnN0IHBhcmFncmFwaCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCg0KI0xvYWRpbmcgTmVzc2VzYXJ5IGxpYnJhcmllcyBmb3Igc2VudGltZW50IEFuYWx5c2lzDQpgYGB7cn0NCmxpYnJhcnkoc2VudGltZW50cikNCmxpYnJhcnkocWRhcCkNCmxpYnJhcnkoanNvbmxpdGUpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0bSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShTZW50aW1lbnRBbmFseXNpcykNCmxpYnJhcnkocXVhbnRlZGEpDQpsaWJyYXJ5KHhsc3gpDQpgYGANCg0KI0NyZWF0aW5nIEFQSSB2YXJpYmxlIGZvciAiQXJ0aWNsZSBTZWFyY2ggQVBJIEZPUk1BVCINCmBgYHtyfQ0KTllUSU1FU19LRVk9ImEwSEEzdUJJU0RrR3l2VUdSM0Zlb0FHeWJ0RFZQUE01Ig0KYGBgDQoNCiNjcmVhdGluZyB0aGUgcXVlcnkgbmVzc2VzYXJ5IHRvIGV4dHJhY3Qgd2FudGVkIGluZm9ybWF0aW9uDQoNCiNQcm9mZXNzb3IgSm9obnNvbiBzdGlsbCBoYXMgdG8gZ2l2ZSBtZSB0aGUgbGlzdCBvZiB3b3JkcyBuZXNzZXNhcnkgZm9yIHF1ZXJ5IA0KDQojRG9lc24ndCBzZWVtIGxpa2Ugd2UgY2FuIGRvICJhbmQiICJvciIgZm9yIHRoZSBzcGVjaWZpYyBxdWVyeSwgc29tZXRoaW5nIHRoYXQgYWNhZGVtaWMgc2VhcmNoIGNvbXBsZXRlIGFuZCBwcm8gcXVlc3QgYXJlIGFibGUgdG8gZG8NCg0KI0p1c3QgZG8gaXQgZm9yIG9uZSBtb250aCAyMDEyLzAxLzAxIC0gMjAxMi8wMi8wMQ0KDQojVGhlIGRlZmF1bHQgY29ubmVjdG9yIGZvciB2YWx1ZXMgaW4gcGFyZW50aGVzZXMgaXMgT1IuIA0KYGBge3J9DQojIExldCdzIHNldCBzb21lIHBhcmFtZXRlcnMNCiN0ZXJtIDwtICJpbW1pZ3JhbnQraW1taWdyYXRpb24iICMgTmVlZCB0byB1c2UgKyB0byBzdHJpbmcgdG9nZXRoZXIgc2VwYXJhdGUgd29yZHMgaG93ZXZlciBpdCBpcyBjb25jYXRpbmF0aW5nDQpiZWdpbl9kYXRlIDwtICIxOTgwMDEwMSINCmVuZF9kYXRlIDwtICIyMDE5MTIwMSIjY2hhbmdlIHRvIDIgbW9udGhzIHRvIGdldCBkYXRhIGZhc3Rlcg0KI2dsb2NhdGlvbnMgPC0gIlUuUyINCmBgYA0KDQojU2VhcmNoaW5nIGZvciB0aGUgdGVybXMgdGhhdCB3ZSBxdWVyeSBhYm92ZSBhbmQgZXNzZW50aWFsbHkgY3JlYXRpbmcgdGhlIHF1ZXJ5IG9iamVjdCBpbiBvcmRlciB0byB1c2UgaXQgZm9yIHRoZSBBUEkNCg0KI3RoZSBodHRwcyBuZWVkcyB0byBiZSB1bmRlcmxpbmVkDQoNCiNpbW1pZ3JhbnQgT1IgbWlncmFudCBPUiBtaWdyYXRpb24gT1IgcmVmdWdlZSBPUiBhc3lsdW0gT1IgdW5kb2N1bWVudGVkIg0KDQojaXQgbmVlZHMgdG8gYmUgZnEgbm90IHENCg0KYGBge3J9DQpiYXNldXJsIDwtIHBhc3RlMCgiaHR0cDovL2FwaS5ueXRpbWVzLmNvbS9zdmMvc2VhcmNoL3YyL2FydGljbGVzZWFyY2guanNvbj9mcT1pbW1pZ3JhbnQgT1IgaW1taWdyYXRpb24gT1IgbWlncmFudCBPUiBtaWdyYXRpb24gT1IgcmVmdWdlZSBPUiBhc3lsdW0gT1IgdW5kb2N1bWVudGVkIiwgDQogICAgICAgICAgICAgICAgICAiJmJlZ2luX2RhdGU9IixiZWdpbl9kYXRlLCImZW5kX2RhdGU9IixlbmRfZGF0ZSwNCiAgICAgICAgICAgICAgICAgICImZmFjZXRfZmlsdGVyPXRydWUmYXBpLWtleT0iLE5ZVElNRVNfS0VZLCBzZXA9IiAiKQ0KYGBgDQoNCg0KI1JldHVybmluZyBhIEpzb24gb2JqZWN0IGFuZCBjYWxjdWxhdGluZyB0aGUgbWF4IHBhZ2VzIGZyb20gdGhlIHF1ZXJ5LCB0aGVyZSBpcyBhIG1heCBvZiAxMCBvYmplY3RzIChuZXdzcGFwZXIgYXJ0aWNsZXMpIHBlciBwYWdlDQpgYGB7cn0NCmluaXRpYWxRdWVyeSA8LSBmcm9tSlNPTihiYXNldXJsKQ0KbWF4UGFnZXMgPC0gcm91bmQoKGluaXRpYWxRdWVyeSRyZXNwb25zZSRtZXRhJGhpdHNbMV0gLyAxMCktMSkgDQpgYGANCg0KI2Zyb20gdGhlIG1heHBhZ2VzIHdlIGFyZSBwYXN0aW5nIHRoZSBiYXNldXJsIGFuZCByZXRyaXZpbmcgdGhlIGluZm9ybWF0aW9uIGFuZCBwdXR0aW5nIGl0IGluIGEgZGF0YWZyYW1lDQoNCiNQdXR0aW5nIHRoZSBzeXN0ZW0gdG8gc2xlZXAgaW4gb3JkZXIgdG8gJ3RyaWNrJyB0aGUgY29tcHV0ZXIgZm9yIHRoZSBhbW91bnQgb2YgcmVxdWVzdHMgbWFkZSBwZXIgbWludXRlDQoNCiNxdWVyeSBmcm9tIEpBTiAyMDEyIC0gMjAxOSBKQU4gdG9vayA+MjQgbWludXRlcyB0byBydW4gd2l0aCBzbGVlcCAzMA0KDQojaXQgZG9lc24ndCBsaWtlIGl0IHdoZW4gdXNpbmcgJT4lIGRhdGEuZnJhbWUoKSBpbiB0aGUgZW5kIG9mIHRoZSB0aGlyZCBsaW5lDQpgYGB7cn0NCiNyZXF1aXJlKHJlc2hhcGUyKQ0KcGFnZXMgPC0gbGlzdCgpDQpmb3IoaSBpbiAwOm1heFBhZ2VzKXsNCiAgbnl0U2VhcmNoIDwtIGZyb21KU09OKHBhc3RlMChiYXNldXJsLCAiJnBhZ2U9IiwgaSksIGZsYXR0ZW4gPSBUUlVFKSAlPiUgZGF0YS5mcmFtZSgpIA0KICBtZXNzYWdlKCJSZXRyaWV2aW5nIHBhZ2UgIiwgaSkNCiAgcGFnZXNbW2krMV1dIDwtIG55dFNlYXJjaCANCiAgU3lzLnNsZWVwKDE1KSAjY2hhbmdlIHRvIDUgdG8gdGVzdCBvbiBzbWFsbGVyIGRhdGFzZXRzLCAzMCBmb3IgYWN0dWFsIGV4ZWN1dGlvbg0KfQ0KYGBgDQpgYGB7cn0NCiNhcy5kYXRhLmZyYW1lKG55dCkNCmBgYA0KDQoNCiNiaW5kaW5nIHRoZSBwYWdlcyBmb3IgdGhlIG5ldyByZXN1bHQNCmBgYHtyfQ0KYWxsTllUU2VhcmNoIDwtcmJpbmRfcGFnZXMocGFnZXMpDQpgYGANCg0KDQojYmluZGluZyB0aGUgcGFnZXMgdG9nZXRoZXIgYW5kIGNyZWF0aW5nIHRoZSBmaW5hbCBkYXRhZnJhbWUuIA0KDQpgYGB7cn0NCmFsbE5ZVFNlYXJjaDIwMTIyMDE5IDwtIHJiaW5kX3BhZ2VzKHBhZ2VzKQ0KYGBgDQoNCiNjcmVhdGluZyBhIGRhdGFmcmFtZSB0aGF0IGFyZSBvbmx5ICJuZXdzIjogRnVuY3Rpb24gcGFydA0KDQojZ2V0dGluZyByaWQgb2YgYW55dGhpbmcgdGhhdCBjb3VsZCBub3QgYmUgIm5ld3MiIHNvIHRoYXQgaXQgZG9lc24ndCBpbnRlcmFjdCB3aXRoIHdyb25nIGRhdGENCmBgYHtyfQ0KZnVuY3RfcmVtb3ZlX3Jvd3M8LSBmdW5jdGlvbihkYXRhRnJhbWUsY29sX2RhdGFmcmFtZSl7DQpub3RfbmV3c192YXJpYWJsZSA8LSBjKCJJbnRlcmFjdGl2ZSBGZWF0dXJlIiwgIlJldmlldyIsICJMZXR0ZXIiLCAiQ29ycmVjdGlvbiIsIkxpc3QiKQ0KYWxsTllUU2VhcmNoX09ubHlOZXdzPDwtZGF0YUZyYW1lWyFncmVwbChwYXN0ZShub3RfbmV3c192YXJpYWJsZSwgY29sbGFwc2U9InwiKSwgY29sX2RhdGFmcmFtZSksXQ0KcmV0dXJuKGFsbE5ZVFNlYXJjaF9Pbmx5TmV3cykNCn0NCmBgYA0KDQoNCiNjYWxsaW5nIHRoZSBmdW5jdGlvbiBvbiB0aGUgc3BlY2lmaWMgY29sdW1uIG9mIGFsbE5ZVFNlYXJjaCBhbmQgcmVtb3ZpbmcgQ28tZWQgYW5kIGVkaXRvcmlhbHMNCg0KYGBge3J9DQpmdW5jdF9yZW1vdmVfcm93cyhhbGxOWVRTZWFyY2gsYWxsTllUU2VhcmNoJHJlc3BvbnNlLmRvY3MudHlwZV9vZl9tYXRlcmlhbCkNCmBgYA0KDQojZ2V0dGluZyByaWQgb2ZmIGZvcmVpZ24gZmllbHMgaW4gbmV3cw0KYGBge3J9DQoNCmZ1bmN0X3JlbW92ZV9ub3RVUzwtIGZ1bmN0aW9uKGRhdGFGcmFtZSxjb2xfZGF0YWZyYW1lKXsNCm5vdF93b3JsZF92YXJpYWJsZSA8LSBjKCJFdXJvcGUiLCJNaWRkbGUgRWFzdCIpDQphbGxOWVRTZWFyY2hfT25seU5ld3NfaW5VUzw8LWRhdGFGcmFtZVshZ3JlcGwocGFzdGUobm90X3dvcmxkX3ZhcmlhYmxlLCBjb2xsYXBzZT0ifCIpLCBjb2xfZGF0YWZyYW1lKSxdDQpyZXR1cm4oYWxsTllUU2VhcmNoX09ubHlOZXdzX2luVVMpDQp9DQoNCmBgYA0KDQoNCiNjYWxsaW5nIHRoZSBmdW5jdGlpb24gb24gDQoNCmBgYHtyfQ0KZnVuY3RfcmVtb3ZlX25vdFVTKGFsbE5ZVFNlYXJjaF9Pbmx5TmV3cyxhbGxOWVRTZWFyY2hfT25seU5ld3MkcmVzcG9uc2UuZG9jcy5zdWJzZWN0aW9uX25hbWUpDQpgYGANCg0KDQoNCiNHZXR0aW5nIHJpZCBvZiB3aGl0ZSBzcGFjZXMNCiN2ZXJpZnkgdGhhdCB0aGlzIGlzIHJpZ2h0DQpgYGB7cn0NCmFsbE5ZVFNlYXJjaF9Pbmx5TmV3c19pblVTJHJlc3BvbnNlLmRvY3MubGVhZF9wYXJhZ3JhcGggPC0oc3RyX3NxdWlzaChhbGxOWVRTZWFyY2hfT25seU5ld3NfaW5VUyRyZXNwb25zZS5kb2NzLmxlYWRfcGFyYWdyYXBoKSkNCmBgYA0KDQojQWRkIElkIHZhcmlhYmxlIHRvIHRoZSBOWVRTZWFyY2hfT25seU5ld3MgDQpgYGB7cn0NCmFsbE5ZVFNlYXJjaF9Pbmx5TmV3cyRpZCA8LSBzZXEuaW50KG5yb3coYWxsTllUU2VhcmNoX09ubHlOZXdzKSkNCmBgYA0KDQoNCg0KI0NvbnZlcnQgZGF0YXJhbWUgaW50byB0ZXJtIGRvY3VtZW50IG1hdHJpeCBmcm9tIHRoZSBhbGxOWVRTZWFyY2hfb25seU5ld3MNCmBgYHtyfQ0KbXlDb3JwdXMgPC0gQ29ycHVzKFZlY3RvclNvdXJjZShhbGxOWVRTZWFyY2hfT25seU5ld3NfaW5VUyRyZXNwb25zZS5kb2NzLmxlYWRfcGFyYWdyYXBoKSkNCmR0bV9OWVRBcnRpY2xlcyA8LSAgRG9jdW1lbnRUZXJtTWF0cml4KG15Q29ycHVzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QocmVtb3ZlUHVuY3R1YXRpb24gPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcHdvcmRzID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvbG93ZXIgPSBUUlVFLA0KICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZU51bWJlcnMgPSBUUlVFKSkgDQpgYGANCg0KDQoNCg0KDQojdGlkeSBmb3JtYXQgc2VudGltZW50IGFuYWx5c2lzDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHRpZHl0ZXh0KQ0KYXBfdGQgPC0gdGlkeShkdG1fTllUQXJ0aWNsZXMpDQpgYGANCg0KI1NlbnRpbWVudCBmcm9tIHRoZSB0ZG0gY3JlYXRlZCBhYm92ZSB3aXRoIHRpZHl2ZXJzZQ0KYGBge3J9DQphcF9zZW50aW1lbnRzIDwtIGFwX3RkICU+JQ0KICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJiaW5nIiksIGJ5ID0gYyh0ZXJtID0gIndvcmQiKSkNCmBgYA0KI1NlbnRpbWVudCBmcm9tIFNlbnRpbWVudEFuYWx5c2lzIHBhY2thZ2Ugd2l0aCBMTSBkaWNjdGlvbmFyeQ0KDQpgYGB7cn0NCnNlbnRpbWVudF9zY29yZUxNX2NsZWFuY29kZTwtIGFuYWx5emVTZW50aW1lbnQoZHRtX05ZVEFydGljbGVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVsZXM9bGlzdCgiU2VudGltZW50TE0iPWxpc3QocnVsZVNlbnRpbWVudCwgbG9hZERpY3Rpb25hcnlMTSgpKSkpDQpgYGANCiNTZW50aW1lbnQgZnJvbSBTZW50aW1lbnRBbmFseXNpcyBwYWNrYWdlIHdpdGggR0kgZGljY3Rpb25hcnkNCg0KDQpgYGB7cn0NCnNlbnRpbWVudF9zY29yZUdJX2NsZWFuY29kZTwtIGFuYWx5emVTZW50aW1lbnQoZHRtX05ZVEFydGljbGVzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVsZXM9bGlzdCgiU2VudGltZW50R0kiPWxpc3QocnVsZVNlbnRpbWVudCwgbG9hZERpY3Rpb25hcnlHSSgpKSkpDQoNCg0KYGBgDQoNCiNTZW50aW1lbnQgZnJvbSBTZW50aW1lbnRBbmFseXNpcyBwYWNrYWdlIGZyb20gcWRhcCBkaWNjdGlvbmFyeQ0KDQpgYGB7cn0NCnNlbnRpbWVudF9zY29yZVFEQVBfY2xlYW5jb2RlPC0gKGFuYWx5emVTZW50aW1lbnQoZHRtX05ZVEFydGljbGVzKSRTZW50aW1lbnRRREFQKQ0Kc2VudGltZW50X3Njb3JlUURBUF9ERjwtYXMuZGF0YS5mcmFtZShzZW50aW1lbnRfc2NvcmVRREFQX2NsZWFuY29kZSkNCmBgYA0KDQoNCiNwdXR0aW5nIHRoZSBkaWNjdGlvbmFyaWVzIGluIGRhdGFmcmFtZQ0KYGBge3J9DQoNCkxNX3Bvc2l0aXZlPC1saXN0KChzdHIoRGljdGlvbmFyeUxNW1sibmVnYXRpdmUiXV0pKSkNCkxNX25lZ2F0aXZlIDwtbGlzdCgoc3RyKERpY3Rpb25hcnlMTVtbInBvc2l0aXZlIl1dKSkpDQpMTV91bmNlcnRhbnRpdHkgPC1saXN0KChzdHIoRGljdGlvbmFyeUxNW1sidW5jZXJ0YWludHkiXV0pKSkNCg0KTE1fZGljY3Rpb25hcnkgPC0gZG8uY2FsbChyYmluZCwgTWFwKGRhdGEuZnJhbWUsIEE9TE1fcG9zaXRpdmUsIEI9TE1fbmVnYXRpdmUsIExNX3VuY2VydGFudGl0eSkpDQoNCmBgYA0KDQoNCiNjb21iaW5pbmlnIDMgc2VudGltZW50IGFuYWx5c2lzIGRhdGFzZXRzDQoNCmBgYHtyfQ0KYWxsX3NlbnRpbWVudF9ERiA8LSBjYmluZChzZW50aW1lbnRfc2NvcmVMTV9jbGVhbmNvZGUsc2VudGltZW50X3Njb3JlR0lfY2xlYW5jb2RlLHNlbnRpbWVudF9zY29yZVFEQVBfREYpDQpgYGANCg0KI3Bsb3R0aW5nIHNlbnRpbWVudHMNCmBgYHtyfQ0KbGlicmFyeShIbWlzYykNCmhpc3QuZGF0YS5mcmFtZShhbGxfc2VudGltZW50X0RGKQ0KYGBgDQoNCg0KDQoNCldPUkQgQ0xPVUQNCmBgYHtyfQ0KbGlicmFyeSgiU25vd2JhbGxDIikNCmxpYnJhcnkoIndvcmRjbG91ZCIpDQpsaWJyYXJ5KCJSQ29sb3JCcmV3ZXIiKQ0KYGBgDQoNCg0KDQojT25seSBydW4gdGhpcyBmb3Igd29yZCBjbG91ZCBwdXJwb3Nlcw0KYGBge3J9DQpkdG1fTllUQXJ0aWNsZXNfd29yZF9jbG91ZCA8LSAgVGVybURvY3VtZW50TWF0cml4KG15Q29ycHVzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QocmVtb3ZlUHVuY3R1YXRpb24gPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcHdvcmRzID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvbG93ZXIgPSBUUlVFLA0KICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZU51bWJlcnMgPSBUUlVFKSkgDQptIDwtIGFzLm1hdHJpeChkdG1fTllUQXJ0aWNsZXNfd29yZF9jbG91ZCkNCnYgPC0gc29ydChyb3dTdW1zKG0pLGRlY3JlYXNpbmc9VFJVRSkNCmQgPC0gZGF0YS5mcmFtZSh3b3JkID0gbmFtZXModiksZnJlcT12KQ0KTiA8LSAxDQoNCm5ld2Q8LWRbLSgxOk4pLCAsIGRyb3AgPSBGQUxTRV0NCmBgYA0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMzQpDQp3b3JkY2xvdWQod29yZHMgPSBuZXdkJHdvcmQsIGZyZXEgPSBkJGZyZXEsIG1pbi5mcmVxID0gMSwNCiAgICAgICAgICBtYXgud29yZHM9MjAwLCByYW5kb20ub3JkZXI9RkFMU0UsIHJvdC5wZXI9MC4zNSwgDQogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOCwgIkRhcmsyIikpDQpgYGANCg0KDQoNCiNjb252ZXJ0IFIgbWFya2Rvd24gdG8gUiBzY3JpcHQNCmBgYHtyfQ0KI2tuaXRyOjpwdXJsKCJDbGVhbl9Db2RlX1NlbnRpbWVudHIuUm1kIiwgIlNjcmlwdF9DbGVhbl9Db2RlX1NlbnRpbWVudCIsIGRvY3VtZW50YXRpb24gPSAyKQ0KYGBgDQojY29kZSBmb3IgdGhlIHdvcmQgdmFsdWVzIG9mIGEgY2VydGFpbiBjb2x1bW4NCmBgYHtyfQ0KYWdncmVnYXRlKGRhdGEuZnJhbWUoY291bnQgPSBhbGxOWVRTZWFyY2hfT25seU5ld3NfaW5VUyRyZXNwb25zZS5kb2NzLnN1YnNlY3Rpb25fbmFtZSksIGxpc3QodmFsdWUgPSBhbGxOWVRTZWFyY2hfT25seU5ld3NfaW5VUyRyZXNwb25zZS5kb2NzLnN1YnNlY3Rpb25fbmFtZSksIGxlbmd0aCkNCmBgYA0KDQojc2F2aW5nIGRhdGEgZnJvbSAyMDE5IHRvIDIwMTIgZm9yIHNlbnRpbWVudCBhbmFseXNpcw0KYGBge3J9DQphbGxOWVRTZWFyY2h0b3NhdmUgPC0gYWxsTllUU2VhcmNoDQphbGxOWVRTZWFyY2h0b3NhdmUkcmVzcG9uc2UuZG9jcy5tdWx0aW1lZGlhIDwtIE5VTEwNCmFsbE5ZVFNlYXJjaHRvc2F2ZSRyZXNwb25zZS5kb2NzLmtleXdvcmRzIDwtIE5VTEwNCmFsbE5ZVFNlYXJjaHRvc2F2ZSRyZXNwb25zZS5kb2NzLmJ5bGluZS5wZXJzb248LSBOVUxMDQojd3JpdGUueGxzeChhbGxOWVRTZWFyY2gsICdhbGxOWVRTZWFyY2gyMDEyLTIwMTktMTQ1OWhpdHMueGxzeCcpDQp3cml0ZS50YWJsZShhbGxOWVRTZWFyY2h0b3NhdmUsICJhbGxOWVRTZWFyY2gyMDEyMjAxOWhpdHMudHh0Iiwgc2VwPSJcdCIpDQpgYGANCg0KDQoNCg0KDQo=